package cc.rengu.igas.cops.core.service.trans.payment;

import cc.rengu.igas.cops.common.enums.RespCodeEnum;
import cc.rengu.igas.cops.common.enums.SignTokenTypeEnum;
import cc.rengu.igas.cops.core.service.base.ManageService;
import cc.rengu.igas.cops.facade.base.BaseResponse;
import cc.rengu.igas.cops.facade.request.ResSignInfoRequest;
import cc.rengu.igas.share.common.constant.TransCacheConstant;
import cc.rengu.igas.share.core.model.UserInfo;
import cc.rengu.igas.share.core.realize.UserService;
import cc.rengu.igas.share.core.realize.impl.UserServiceImpl;
import cc.rengu.oltp.service.base.ChannelBaseService;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.SignAcctInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.SignAcctInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.SignAcctInfo;
import cc.rengu.oltp.service.common.enums.AcctTypeEnum;
import cc.rengu.oltp.service.common.enums.CheckResultEnum;
import cc.rengu.oltp.service.common.enums.TransStatusEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.model.OrderInfo;
import cc.rengu.oltp.service.realize.TransCustomImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;

import java.util.List;
import java.util.stream.Collectors;

public class CopsResSignInfoService extends ManageService implements TransCustomImpl {
    OrderInfo orderInfo = null;

    @Override
    protected Object bizBeforeCust() throws Exception {
        ResSignInfoRequest resSignInfoRequest = new ResSignInfoRequest();
        ConvertUtil.convertOutput(resSignInfoRequest);
        return resSignInfoRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        ResSignInfoRequest resSignInfoRequest = (ResSignInfoRequest) request;
        String instId = resSignInfoRequest.getHeader().getInstId();
        String userId = resSignInfoRequest.getUserId();
        String payAcctNo = resSignInfoRequest.getPayAcctNo();
        BizResponse<BaseResponse> bizResponse = new BizResponse<>();

        UserService userService = new UserServiceImpl();
        UserInfo userInfo = userService.getUserInfo(instId, userId, resSignInfoRequest.getHeader().getSession());
        if (null == userInfo) {
            rglog.error("获取用户信息失败!");
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }

        //step1.获取用户签约主体
        String signInst = userService.getUserSignInst();

        //step2.用户密码校验
        boolean checkResult = userService.checkUserPayPassword(instId, resSignInfoRequest.getUserId(), null, resSignInfoRequest.getPassword());
        if (!checkResult) {
            rglog.error("用户密码错误!");
            throw new BizException(RespCodeEnum.USER_PASSWORD_ERROR.getRespCode(), RespCodeEnum.USER_PASSWORD_ERROR.getRespDesc());
        }

        //step3.根据请求信息获取所有待解析的签约信息
        List<SignAcctInfo> signAcctInfoList;
        SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
        if (StringUtil.isEmptyOrNull(resSignInfoRequest.getSignToken())) {
            signAcctInfoList = signAcctInfoMapper.selectSignAcctInfoBySignTyUserId(instId, userId, signInst);
            //获取卡号匹配的已签约数据
            signAcctInfoList = signAcctInfoList.stream().filter(signAcctInfo -> signAcctInfo.getSignAcctNo().endsWith(payAcctNo) &&
                    signAcctInfo.getSignStatus().equals(AppParamConstant.YES)).collect(Collectors.toList());
            if (signAcctInfoList.size() == 0) {
                rglog.info("签约状态为已签约且满足下列条件的签约关系不存在,instId:<{}>,userId:<{}>,payAcctNo:<>{}", instId, userId, payAcctNo);
                throw new BizException(RespCodeEnum.INVALID_SIGN.getRespCode(), RespCodeEnum.INVALID_SIGN.getRespDesc());
            }
            //判断是否存在其它签约主体的签约关系
            List<SignAcctInfo> signAcctInfos = signAcctInfoMapper.selectSignAcctInfoBySignAcctNo(instId, payAcctNo);
            List<SignAcctInfo> otherSignInstSignAcctList = signAcctInfos.stream().filter(signAcctInfo -> !signAcctInfo.getSignInst().equals(signInst)).collect(Collectors.toList());
            if (otherSignInstSignAcctList.size() != 0) {
                rglog.debug("用户存在多个签约主体");
                String unSignSysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
                for (SignAcctInfo signAcctInfo : signAcctInfoList) {
                    if (signInst.equals(signAcctInfo.getSignInst())) {
                        udpateSignAcctInfo(signAcctInfoMapper, signAcctInfo, unSignSysSeqNum);
                    }
                }
                bizResponse.setRspSysId(AppParamConstant.SYS_ID);
                bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
                bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
                return bizResponse;
            }
        } else {
            signAcctInfoList = signAcctInfoMapper.selectSignAcctInfoBySignToken(instId, resSignInfoRequest.getSignToken());
        }
        if (null == signAcctInfoList || signAcctInfoList.isEmpty()) {
            rglog.info("用户不存在签约关系,instId:<{}>,userId:<{}>", instId, userId);
            throw new BizException(RespCodeEnum.GET_SIGN_INFO_ERROR.getRespCode(), RespCodeEnum.GET_SIGN_INFO_ERROR.getRespDesc());
        }

        //step4.签约账号解约
        if (null == txnInfo.getChannelCallCfgList() || txnInfo.getChannelCallCfgList().isEmpty()) {
            rglog.error("<{}-{}>交易未配置交易通道服务调用配置信息！", txnInfo.getSrcTxnAuthCfg().getTxnNum(), txnInfo.getSrcTxnAuthCfg().getTxnName());
            throw new BizException(RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespCode(), RespCodeEnum.CHANNEL_CONFIG_NOT_EXIST.getRespDesc());
        }

        for (SignAcctInfo signAcctInfo : signAcctInfoList) {
            //将需要解析的签约信息设置到交易缓存中
            GlobalTransUtil.setCacheValue(TransCacheConstant.SIGN_ACCT_INFO, signAcctInfo);
            List<ChannelCallCfg> channelCallCfgList = txnInfo.getChannelCallCfgList().stream().filter(item ->
                    item.getCallIndex().equals(ChannelBaseService.FIRST_CHANNEL_CALL_INDEX)).collect(Collectors.toList());
            ChannelCallCfg channelCallCfg = channelCallSceneDiscern(resSignInfoRequest, channelCallCfgList);
            //通道服务调用
            Class channelClasz = Class.forName(channelCallCfg.getCallChannelImpl());
            ChannelBaseService channelBaseService = (ChannelBaseService) channelClasz.newInstance();
            channelBaseService.callService(txnInfo, (null == orderInfo) ? new OrderInfo() : orderInfo, channelCallCfg.getBizScene(), request);
            //将设置的签约信息清除
            GlobalTransUtil.removeCacheValue(TransCacheConstant.SIGN_ACCT_INFO);
        }

        //step5.拼装返回结果
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        BaseResponse baseResponse = (BaseResponse) bizResponse.getResult();
        ConvertUtil.convertInput(baseResponse);
    }

    /**
     * 更新签约信息表签约状态
     *
     * @param signAcctInfo    签约实体
     * @param unSignSysSeqNum 解约流水号
     */
    private void udpateSignAcctInfo(SignAcctInfoMapper signAcctInfoMapper, SignAcctInfo signAcctInfo, String unSignSysSeqNum) throws Exception {
        signAcctInfo.setUnsignSysSeqNum(unSignSysSeqNum);
        signAcctInfo.setUnsignDate(DateUtil.getCurrentDate());
        signAcctInfo.setSignStatus(AppParamConstant.NO);
        signAcctInfo.setUpdateTime(DateUtil.getCurrentDateTime("yyyy-MM-dd HH:mm:ss.SSS"));
        int recode = signAcctInfoMapper.updateSignAcctInfoByPrimaryKey(signAcctInfo);
        if (recode != 0) {
            rglog.info("更新签约信息表签约状态为解约-失败:{}", JSON.toJSONString(signAcctInfo));
            throw new BizException(RespCodeEnum.UPDATE_SIGN_ACCT_ERROR.getRespCode(), RespCodeEnum.UPDATE_SIGN_ACCT_ERROR.getRespDesc());
        } else {
            rglog.debug("更新签约信息表签约状态为解约-成功:{}", JSON.toJSONString(signAcctInfo));
        }
    }

    @Override
    public ChannelCallCfg channelCallSceneDiscern(Object request, List<ChannelCallCfg> channelCallCfgList) throws Exception {
        List<ChannelCallCfg> channelCallCfgs = null;
        SignAcctInfo signAcctInfo = (SignAcctInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.SIGN_ACCT_INFO);
        if (null != signAcctInfo) {
            if (SignTokenTypeEnum.BANK_QUICK_PAY.getSignTypeCode().equals(signAcctInfo.getSignTokenType())) {
                if (AcctTypeEnum.BANK_DEBIT.getAcctType().equals(signAcctInfo.getSignAcctType())) {
                    rglog.info("本行借记卡签约关系解约,调用核心签约接口进行解约，signAcctType:<{}>", signAcctInfo.getSignAcctType());
                    channelCallCfgs = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("00")).collect(Collectors.toList());
                } else if (AcctTypeEnum.BANK_CREDIT.getAcctType().equals(signAcctInfo.getSignAcctType())) {
                    rglog.info("本行贷记卡签约关系解约,调用核心签约接口进行解约，signAcctType:<{}>", signAcctInfo.getSignAcctType());
                    channelCallCfgs = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("01")).collect(Collectors.toList());
                }
            } else if (SignTokenTypeEnum.UPAC_TOKEN.getSignTypeCode().equals(signAcctInfo.getSignTokenType())) {
                rglog.debug("银联无跳转签约关系解约，调用银联无跳转通道进行解约");
                channelCallCfgs = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("02")).collect(Collectors.toList());
            } else if (SignTokenTypeEnum.NCQS_PAY.getSignTypeCode().equals(signAcctInfo.getSignTokenType())) {
                rglog.debug("银联无卡快捷签约关系解约,调用银联无卡快捷通道进行解约");
                channelCallCfgs = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("03")).collect(Collectors.toList());
            } else if (SignTokenTypeEnum.NUCC_PAY.getSignTypeCode().equals(signAcctInfo.getSignTokenType())) {
                rglog.debug("网联签约关系解约,调用网联通道进行解约");
                channelCallCfgs = channelCallCfgList.stream().filter(item -> item.getBizScene().equals("04")).collect(Collectors.toList());
            }
        }
        if (null != channelCallCfgs) {
            if (channelCallCfgs.size() > 1) {
                rglog.error("业务场景为<{}>，调用序号为<{}>存在多条配置，请检查配置!", channelCallCfgs.get(0).getBizScene(), channelCallCfgList.get(0).getCallIndex());
                return null;
            } else {
                return channelCallCfgs.stream().findFirst().orElse(null);
            }
        }
        return null;
    }

    @Override
    public CheckResultEnum channelCallPreCheck(Object request, ChannelCallCfg channelCallCfg, OrderInfo orderInfo) throws Exception {
        return CheckResultEnum.PASSED;
    }

    @Override
    public TransStatusEnum channelCallResultProc(Object request, ChannelCallCfg channelCallCfg, TransStatusEnum transStatusEnum, Object channelResponse, OrderInfo needUpdateOrderInfo) throws Exception {
        if (TransStatusEnum.TRANS_SUCC.equals(transStatusEnum)) {
            XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
            SignAcctInfoMapper signAcctInfoMapper = new SignAcctInfoMapperImpl();
            SignAcctInfo signAcctInfo = (SignAcctInfo) GlobalTransUtil.getCacheValue(TransCacheConstant.SIGN_ACCT_INFO);
            if (null != signAcctInfo) {
                String unSignSysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM);
                udpateSignAcctInfo(signAcctInfoMapper, signAcctInfo, unSignSysSeqNum);
            }
        }
        return transStatusEnum;
    }
}
